#include <pthread.h>
#include <unistd.h>

#include "packet_free_task.h"
#include "log.h"
#include "mem.h"
#include "core_data.h"

#define USLEEP_TIME 500000
#define SLEEP_TIME 5

int packet_free_ops(struct msg *msg)
{
	log_info("begin packet_free_ops.");

	return 0;
}

void *packet_free_loop(void *data)
{
	log_info("begin packet_free_loop.");	

	struct core_data_queue *core_data_queue = NULL;

	core_data_queue = core_conf.core_data_queue;

	if (core_data_queue == NULL) {
		log_error("core_data_queue is NULL.");
		return NULL;
	}

	while (1) {
		/* TODO: it should be changeable. */
		unsigned long buffer_size = 3 * core_data_queue->max_id / 4; 

		pthread_mutex_lock(&(core_data_queue->lock));	
		
		if (core_data_queue->dont_free > 0) {
			pthread_mutex_unlock(&(core_data_queue->lock));	
			usleep(USLEEP_TIME);
			continue;
		}

		/* we make buffer_size + 2 to promise core_data_queue->tail->prev is not NULL. */
		if (core_data_queue->count <= buffer_size + 2) {
			pthread_mutex_unlock(&(core_data_queue->lock));	
			sleep(SLEEP_TIME);
			continue;
		}

		struct core_data *core_data;
		if (core_data_queue->mode == MODE_DEFAULT) {
			core_data = core_data_queue->core_data_tail;
			pthread_mutex_lock(&(core_data->lock));

			if (core_data->ref != 0) {
				pthread_mutex_unlock(&(core_data->lock));
				pthread_mutex_unlock(&(core_data_queue->lock));	
				usleep(USLEEP_TIME);
				continue;
			}
			
			struct core_data *be_free = core_data;
			core_data = core_data->prev;

			remove_core_data_at_tail(core_data_queue);

			pthread_mutex_unlock(&(core_data_queue->lock));	
			pthread_mutex_unlock(&(be_free->lock));
				
			core_data_free(be_free);

			continue;
		} else if (core_data_queue->mode == MODE_NOTHING) {
			/* In this mode, do nothing here. */
			pthread_mutex_unlock(&(core_data_queue->lock));	
		}
	}
}
